#include "AsioIoContextPool.hpp"
#include "CServer.hpp"
#include "ChatServiceImpl.hpp"
#include "RedisMgr.hpp"
#include "const.hpp"
#include <boost/asio.hpp>
#include <boost/asio/io_context.hpp>
#include <boost/asio/signal_set.hpp>
#include <boost/property_tree/ini_parser.hpp>
#include <boost/property_tree/ptree.hpp>
#include <csignal>
#include <exception>
#include <grpcpp/impl/service_type.h>
#include <grpcpp/security/server_credentials.h>
#include <grpcpp/server_builder.h>
#include <iostream>
#include <memory>
#include <string>
#include <thread>

bool bstop = false;
boost::property_tree::ptree config;

int main(int argc, char *argv[]) {
  try {
    std::string config_path;
    if (argc == 1) {
      config_path = "config.ini";
    }
    if (argc == 2) {
      config_path = argv[1];
    }
    if (argc > 2) {
      return -1;
    }
    std::cout << "config_path: " << config_path << std::endl;
    boost::property_tree::ini_parser::read_ini(config_path, config);
    // 根据配置文件获取当前服务器的名称
    std::string server_name = config.get<std::string>("SelfServer.Name");
    // 向redis中写入当前已建立连接的数量 0
    RedisMgr::GetInstance().HSet(LOGIN_COUNT, server_name, "0");
    // 启动grpc服务
    std::string server_host = config.get<std::string>("SelfServer.Host");
    std::string rpc_port = config.get<std::string>("SelfServer.RPCPort");
    std::string server_address(server_host + ":" + rpc_port);
    ChatServiceImpl service;
    grpc::ServerBuilder builder;
    // 监听端口和添加服务
    builder.AddListeningPort(server_address, grpc::InsecureServerCredentials());
    builder.RegisterService(&service);
    // 构建并启动grpc服务
    std::unique_ptr<grpc::Server> server(builder.BuildAndStart());
    // 单独的一个线程中启动grpc服务
    std::thread grpc_server_thread([&]() { server->Wait(); });
    std::cout << "RPC Server listening on " << server_address << std::endl;

    auto &pool = AsioIoContextPool::GetInstance();
    boost::asio::io_context io_context;
    boost::asio::signal_set signals(io_context, SIGINT, SIGTERM);
    signals.async_wait([&](boost::system::error_code ec, int t) {
      io_context.stop();
      pool.Stop();
      server->Shutdown();
    });
    auto port_str = config.get<std::string>("SelfServer.Port");
    // 启动服务器
    CServer s(io_context, atoi(port_str.c_str()));
    io_context.run();
    RedisMgr::GetInstance().HDel(LOGIN_COUNT, server_name);
    RedisMgr::GetInstance().Close();
    grpc_server_thread.join();
  } catch (std::exception &e) {
    std::cout << "Exception: " << e.what() << std::endl;
  }
  return 0;
}